parte 4: parser recursivo descendiente de un lisp
Los compiladores recursivos descendientes implementan el stack del parser LL1 de forma implícita en el stack de ejecución. Así, en vez de aplicar una regla de producción, se llama a una función que ejecuta la regla de producción.
El parser recursivo descendiente tiene un método para cada símbolo no terminal. Para cada uno de ellos, se ejecutará un programa que se puede deducir interpretando el diagrama de sintaxis como un diagrama de flujo.
- Cada vez que debe encontrarse con un terminal en el diagrama de flujo, se invoca la función
match(TokenType)
, que verifica que el token sea el correcto y lo elimina; o lanza una excepción, si el token no es correcto. - Cuando debe encontrarse con un no terminal, se invoca el método correspondiente a ese no terminal.
Todas las bifurcaciones del diagrama de sintaxis debe poder decidirse mirando únicamente el siguiente token, si la gramática es LL1.
#
Estructura del códigoCompilispParser
es un parser de Compilisp
, la sintaxis del lab 1. Debe implementar los métodos correspondientes a cada no terminal:
input()
line()
sExp()
list()
atom()
Cada uno debe representar el diagrama de sintaxis correspondiente a un símbolo no terminal. Para esto, además de invocar los otros métodos-reglas, deben invocar los siguientes métodos (incluídos en el esqueleto):
match(TokenType)
:- Si el
TokenType
coincide con el siguiente del programa, lo remueve - Si no coincide, arroja una excepción
- Si el
nextToken()
devuelve el siguiente token sin eliminarlo. Si el programa terminó, arroja una excepción.getProgramIsOver()
devuelve un booleano indicando si el programa terminó o no
#
Especificación informal de la semánticaEste lenguaje es un lisp, con lo cual puede usarse scheme (sudo apt install mit-scheme
) para probar algunas expresiones y "construir más test" y jugar con un lenguaje similar a compilisp.
Estético: devuelve un texto que es la concatenación de las líneas.
Estético: devuelve el valor de la sExp convertido a un string.
- Si es atom: devuelve el valor del atom
- si es list y su evaluación no está inhibida: Evaluación de la secuencia de (en caso de que no esté quoteada). El primer es la función y los siguientes son argumentos.
- Si es list y su evaluación está inhibida: devuelve una lista.
En el caso de number y string, devuelve el valor correspondiente. En el caso del símbolo, revisa si existe alguna variable con ese nombre y devuelve su valor.
Devuelve una lista vacía
Devuelve un listado de los de adentro. El punto no hace ninguna diferencia, es estético.
Devuelve en sExp de adentro inhibiendo su evaluación.
#
ConsignaCompletar los métodos de CompilispParser.java
de forma que pasen los tests de test/.../parte4/CompilispParserTest.java
..
#
Consejos- Implementar unicamente las funcionalidades requeridas para que los test pasen (es decir,
+
y-
), no más. - Abusar del tipo
Object
. No implementarCompilispParser
utilizando tipos seguros. CompilispParser
debe evaluar el programa a medida que lo interpreta. Se recomienda llamar a la función de evaluación ensExp
. La lista iniciada conQUOTE
debe inhibir la evaluación de su contenido.- Se recomienda desarrollar una función recursiva que convierta su contenido a
string
, e invocarla desdeline()
.